package com.platform.web.controller.module;

import com.platform.common.annotation.Log;
import com.platform.common.core.controller.BaseController;
import com.platform.common.core.domain.AjaxResult;
import com.platform.common.core.domain.Ztree;
import com.platform.common.core.page.TableDataInfo;
import com.platform.common.core.text.Convert;
import com.platform.common.enums.BusinessType;
import com.platform.common.utils.netty.ChannelSupervise;
import com.platform.common.utils.netty.NettyUtil;
import com.platform.common.utils.poi.ExcelUtil;
import com.platform.common.utils.redis.RedisRun;
import com.platform.common.utils.redis.RedisUtil;
import com.platform.framework.util.ShiroUtils;
import com.platform.module.domain.BaseCalorimeterData;
import com.platform.module.domain.BaseCalorimeterType;
import com.platform.module.domain.LinkConcentratorMeter;
import com.platform.module.service.IBaseCalorimeterDataService;
import com.platform.module.service.IBaseCalorimeterTypeService;
import com.platform.module.service.ILinkConcentratorMeterService;
import com.platform.system.service.ISysDictDataService;
import io.netty.channel.Channel;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * 热量表设备数据Controller
 *
 * @author wangqi
 * @date 2020-07-13
 */
@Controller
@RequestMapping("/module/calorimeter/data")
public class BaseCalorimeterDataController extends BaseController
{
    private String prefix = "module/calorimeter/data";

    @Autowired
    private ILinkConcentratorMeterService linkConcentratorMeterService;

    @Autowired
    private IBaseCalorimeterDataService baseCalorimeterDataService;

    @Autowired
    private IBaseCalorimeterTypeService baseCalorimeterTypeService;

    @Autowired
    private ISysDictDataService sysDictDataService;

    @Autowired
    private RedisUtil redisUtil;

    @RequiresPermissions("module:calorimeter:data:view")
    @GetMapping("/{typeId}")
    public String data(@PathVariable("typeId") Long typeId, ModelMap mmap)
    {
        BaseCalorimeterType baseCalorimeterType = new BaseCalorimeterType();
        if(typeId != 0L){
            baseCalorimeterType = baseCalorimeterTypeService.getById(typeId);
        }
        mmap.put("type", baseCalorimeterType);
        mmap.put("calorimeterList", baseCalorimeterTypeService.list());
        return prefix + "/data";
    }

    /**
     * 查询热量表设备数据列表
     */
    @RequiresPermissions("module:calorimeter:data:list")
    @PostMapping("/list")
    @ResponseBody
    public TableDataInfo list(BaseCalorimeterData baseCalorimeterData)
    {
        startPage();
        List<BaseCalorimeterData> list = baseCalorimeterDataService.selectBaseCalorimeterDataList(baseCalorimeterData);
        return getDataTable(list);
    }

    /**
     * 导出热量表设备数据列表
     */
    @RequiresPermissions("module:calorimeter:data:export")
    @Log(title = "热量表设备数据", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    @ResponseBody
    public AjaxResult export(BaseCalorimeterData baseCalorimeterData)
    {
        List<BaseCalorimeterData> list = baseCalorimeterDataService.selectBaseCalorimeterDataList(baseCalorimeterData);
        ExcelUtil<BaseCalorimeterData> util = new ExcelUtil<BaseCalorimeterData>(BaseCalorimeterData.class);
        for(BaseCalorimeterData data : list){
            String status = sysDictDataService.selectDictLabel("status", data.getStatus());
            data.setStatus(status);
        }
        return util.exportExcel(list, "热量表资料");
    }

    /**
     * @Author 王琦
     * @Description //热量表型号信息导入
     * @Date 2020/6/19 19:56
     * @Param [file, updateSupport]
     * @return com.platform.common.core.domain.AjaxResult
     */
    @Log(title = "热量表数据导入", businessType = BusinessType.IMPORT)
    @RequiresPermissions("module:calorimeter:data:import")
    @PostMapping("/importData")
    @ResponseBody
    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
    {
        ExcelUtil<BaseCalorimeterData> util = new ExcelUtil<BaseCalorimeterData>(BaseCalorimeterData.class);
        List<BaseCalorimeterData> calorimeterDataList = util.importExcel(file.getInputStream());
        String operName = ShiroUtils.getSysUser().getLoginName();
        String message = baseCalorimeterDataService.importBaseCalorimeterData(calorimeterDataList, updateSupport, operName);
        return AjaxResult.success(message);
    }

    /**
     * @Author 王琦
     * @Description //导入模板
     * @Date 2020/6/19 19:56
     * @Param []
     * @return com.platform.common.core.domain.AjaxResult
     */
    @GetMapping("/importTemplate")
    @ResponseBody
    public AjaxResult importTemplate()
    {
        ExcelUtil<BaseCalorimeterData> util = new ExcelUtil<BaseCalorimeterData>(BaseCalorimeterData.class);
        return util.importTemplateExcel("热量表信息");
    }

    /**
     * 新增热量表设备数据
     */
    @GetMapping("/add/{typeId}")
    public String add(@PathVariable("typeId") Long typeId, ModelMap mmap)
    {
        List<BaseCalorimeterType> calorimeterList = baseCalorimeterTypeService.list();
        mmap.put("calorimeterList", calorimeterList);
        mmap.put("typeId", typeId);
        return prefix + "/add";
    }

    /**
     * 新增保存热量表设备数据
     */
    @RequiresPermissions("module:calorimeter:data:add")
    @Log(title = "热量表设备数据", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    @ResponseBody
    public AjaxResult addSave(BaseCalorimeterData baseCalorimeterData)
    {
        baseCalorimeterData.setCreateBy(ShiroUtils.getLoginName());
        return toAjax(baseCalorimeterDataService.insertBaseCalorimeterData(baseCalorimeterData));
    }

    /**
     * 修改热量表设备数据
     */
    @GetMapping("/edit/{dataId}")
    public String edit(@PathVariable("dataId") Long dataId, ModelMap mmap)
    {
        BaseCalorimeterData baseCalorimeterData = baseCalorimeterDataService.getById(dataId);
        mmap.put("baseCalorimeterData", baseCalorimeterData);
        List<BaseCalorimeterType> calorimeterList = baseCalorimeterTypeService.list();
        mmap.put("calorimeterList", calorimeterList);
        return prefix + "/edit";
    }

    /**
     * 修改保存热量表设备数据
     */
    @RequiresPermissions("module:calorimeter:data:edit")
    @Log(title = "热量表设备数据", businessType = BusinessType.UPDATE)
    @PostMapping("/edit")
    @ResponseBody
    public AjaxResult editSave(BaseCalorimeterData baseCalorimeterData)
    {
        baseCalorimeterData.setUpdateBy(ShiroUtils.getLoginName());
        return toAjax(baseCalorimeterDataService.updateBaseCalorimeterData(baseCalorimeterData));
    }

    /**
     * 删除热量表设备数据
     */
    @RequiresPermissions("module:calorimeter:data:remove")
    @Log(title = "热量表设备数据", businessType = BusinessType.DELETE)
    @PostMapping( "/remove")
    @ResponseBody
    public AjaxResult remove(String ids)
    {
        return toAjax(baseCalorimeterDataService.deleteBaseCalorimeterDataByIds(ids));
    }

    /**
     * 热表登记
     */
    @Log(title = "热表登记", businessType = BusinessType.GRANT)
    @RequiresPermissions("module:calorimeter:data:register")
    @PostMapping("/register")
    @ResponseBody
    public AjaxResult register(String calorimeterIds) throws InterruptedException {
        List<String> ids = Arrays.asList(Convert.toStrArray(calorimeterIds));
        StringBuilder failureMsg = new StringBuilder();
        for(String calorimeterId : ids){
            //获取热表信息
            BaseCalorimeterData calorimeterData = baseCalorimeterDataService.selectBaseCalorimeterData(calorimeterId);

            String concentratorId = "";

            if(redisUtil.hHasKey("concentratorMeter", calorimeterId)){
                concentratorId = redisUtil.hget("concentratorMeter", calorimeterId).toString();
            }else{
                failureMsg.append("热表"+calorimeterId+"未关联采集器，请先关联采集器");
                break;
            }

            boolean status = redisUtil.hHasKey("sys-netty", concentratorId);
            if(!status){
                failureMsg.append("采集器"+concentratorId+"已离线，请联系现场维护人员重启采集器");
                break;
            }
            //获取采集器高位
            String cenhigh = concentratorId.substring(0,2);
            //获取采集器低位
            String cenlow = concentratorId.substring(2,4);

            //获取通道id
            String channelId = redisUtil.hget("sys-netty",cenhigh+cenlow).toString();
            Channel channel = ChannelSupervise.findChannel(channelId);
            if(channel==null){
                failureMsg.append("采集器"+concentratorId+"已离线，请联系现场维护人员重启采集器");
                break;
            }

            String add3 = calorimeterData.getCalorimeterId().substring(0,2);
            String add4 = calorimeterData.getCalorimeterId().substring(2,4);
            String add5 = calorimeterData.getCalorimeterId().substring(4,6);
            String add6 = calorimeterData.getCalorimeterId().substring(6,8);
            //控制码
            String cont = "03";
            //获取设备厂商编码
            String factory = calorimeterData.getFactory().getFactoryNumber();
            //计算校验码
            int ll = NettyUtil.get10HexNum(cenhigh)+NettyUtil.get10HexNum(cenlow)+NettyUtil.get10HexNum(add3)+NettyUtil.get10HexNum(add4)+NettyUtil.get10HexNum(add5)+NettyUtil.get10HexNum(add6)+NettyUtil.get10HexNum(cont)+NettyUtil.get10HexNum(factory);
            String check = NettyUtil.get16HexNum(ll);
            if(check.length()<2){
                check = "0" + check;
            }else{
                check = check.substring(check.length()-2);
            }
            String response = "AA "+ cenlow +" "+ cenhigh + " " + add3 + " " + add4 + " " + add5 + " " + add6 + " " + cont + " " + factory + " 00 00 00 00 00 " + check + " FF ";
            String revertStr = response.replace(" ", "");
            NettyUtil.writeToClient(revertStr,channel,"热表登记");
            CountDownLatch countDownLatch = new CountDownLatch(1);
            new Thread(new RedisRun(countDownLatch,redisUtil,calorimeterId,cont)).start();
            countDownLatch.await();
            String result = RedisRun.result;
            if(result.equals("00") || result.equals("01")){
                LinkConcentratorMeter linkConcentratorMeter = new LinkConcentratorMeter();
                linkConcentratorMeter.setCalorimeterId(calorimeterId);
                linkConcentratorMeter.setConcentratorId(concentratorId);
                linkConcentratorMeter.setStatus("1");
                linkConcentratorMeterService.updateLinkConcentratorMeter(linkConcentratorMeter);
            }else{
                failureMsg.append("<br/>热表"+calorimeterData.getCalorimeterId()+"登记失败");
            }
        }
        if(failureMsg.toString().equals("")){
            return AjaxResult.success();
        }else{
            return AjaxResult.error(failureMsg.toString());
        }
    }

    /**
     * 热表注销
     */
    @Log(title = "热表注销", businessType = BusinessType.GRANT)
    @RequiresPermissions("module:calorimeter:data:cancel")
    @PostMapping("/cancel")
    @ResponseBody
    public AjaxResult cancel(String calorimeterIds) throws InterruptedException {
        List<String> ids = Arrays.asList(Convert.toStrArray(calorimeterIds));
        StringBuilder failureMsg = new StringBuilder();
        for(String calorimeterId : ids){
            //获取热表信息
            BaseCalorimeterData calorimeterData = baseCalorimeterDataService.selectBaseCalorimeterData(calorimeterId);

            String concentratorId = "";

            if(redisUtil.hHasKey("concentratorMeter", calorimeterId)){
                concentratorId = redisUtil.hget("concentratorMeter", calorimeterId).toString();
            }else{
                failureMsg.append("热表"+calorimeterId+"未关联采集器，请先关联采集器");
                break;
            }
            boolean status = redisUtil.hHasKey("sys-netty", concentratorId);
            if(!status){
                failureMsg.append("采集器"+concentratorId+"已离线，请联系现场维护人员重启采集器");
                break;
            }
            //获取采集器高位
            String cenhigh = concentratorId.substring(0,2);
            //获取采集器低位
            String cenlow = concentratorId.substring(2,4);

            //获取通道id
            String channelId = redisUtil.hget("sys-netty",cenhigh+cenlow).toString();
            Channel channel = ChannelSupervise.findChannel(channelId);
            if(channel==null){
                failureMsg.append("采集器"+concentratorId+"已离线，请联系现场维护人员重启采集器");
                break;
            }

            String add3 = calorimeterData.getCalorimeterId().substring(0,2);
            String add4 = calorimeterData.getCalorimeterId().substring(2,4);
            String add5 = calorimeterData.getCalorimeterId().substring(4,6);
            String add6 = calorimeterData.getCalorimeterId().substring(6,8);
            //控制码
            String cont = "04";
            //获取设备厂商编码
            String factory = calorimeterData.getFactory().getFactoryNumber();
            //计算校验码
            int ll = NettyUtil.get10HexNum(cenhigh)+NettyUtil.get10HexNum(cenlow)+NettyUtil.get10HexNum(add3)+NettyUtil.get10HexNum(add4)+NettyUtil.get10HexNum(add5)+NettyUtil.get10HexNum(add6)+NettyUtil.get10HexNum(cont)+NettyUtil.get10HexNum(factory);
            String check = NettyUtil.get16HexNum(ll);
            if(check.length()<2){
                check = "0" + check;
            }else{
                check = check.substring(check.length()-2);
            }
            String response = "AA "+ cenlow +" "+ cenhigh + " " + add3 + " " + add4 + " " + add5 + " " + add6 + " " + cont + " " + factory + " 00 00 00 00 00 " + check + " FF ";
            String revertStr = response.replace(" ", "");
            NettyUtil.writeToClient(revertStr,channel,"热表注销");
            CountDownLatch countDownLatch = new CountDownLatch(1);
            new Thread(new RedisRun(countDownLatch,redisUtil,calorimeterData.getCalorimeterId(),cont)).start();
            countDownLatch.await();
            String result = RedisRun.result;
            if(result.equals("00") || result.equals("02")){
                LinkConcentratorMeter linkConcentratorMeter = new LinkConcentratorMeter();
                linkConcentratorMeter.setCalorimeterId(calorimeterId);
                linkConcentratorMeter.setConcentratorId(concentratorId);
                linkConcentratorMeter.setStatus("0");
                linkConcentratorMeterService.updateLinkConcentratorMeter(linkConcentratorMeter);
            }else{
                failureMsg.append("<br/>热表"+calorimeterData.getCalorimeterId()+"注销失败");
            }
        }
        if(failureMsg.toString().equals("")){
            return AjaxResult.success();
        }else{
            return AjaxResult.error(failureMsg.toString());
        }
    }

    /**
     * 读取热表数据
     */
    @Log(title = "读取热表数据", businessType = BusinessType.GRANT)
    @RequiresPermissions("module:calorimeter:data:check")
    @PostMapping("/check")
    @ResponseBody
    public AjaxResult check(String calorimeterIds) throws InterruptedException {
        List<String> ids = Arrays.asList(Convert.toStrArray(calorimeterIds));
        StringBuilder failureMsg = new StringBuilder();
        for(String calorimeterId : ids){
            //获取热表信息
            BaseCalorimeterData calorimeterData = baseCalorimeterDataService.selectBaseCalorimeterData(calorimeterId);

            String concentratorId = "";

            if(redisUtil.hHasKey("concentratorMeter", calorimeterId)){
                concentratorId = redisUtil.hget("concentratorMeter", calorimeterId).toString();
            }else{
                failureMsg.append("热表"+calorimeterId+"未关联采集器，请先关联采集器");
                break;
            }
            boolean status = redisUtil.hHasKey("sys-netty", concentratorId);
            if(!status){
                failureMsg.append("采集器"+concentratorId+"已离线，请联系现场维护人员重启采集器");
                break;
            }
            //获取采集器高位
            String cenhigh = concentratorId.substring(0,2);
            //获取采集器低位
            String cenlow = concentratorId.substring(2,4);

            //获取通道id
            String channelId = redisUtil.hget("sys-netty",cenhigh+cenlow).toString();
            Channel channel = ChannelSupervise.findChannel(channelId);
            if(channel==null){
                failureMsg.append("采集器"+concentratorId+"已离线，请联系现场维护人员重启采集器");
                break;
            }

            String add3 = calorimeterData.getCalorimeterId().substring(0,2);
            String add4 = calorimeterData.getCalorimeterId().substring(2,4);
            String add5 = calorimeterData.getCalorimeterId().substring(4,6);
            String add6 = calorimeterData.getCalorimeterId().substring(6,8);
            //控制码
            String cont = "01";
            //获取设备厂商编码
            String factory = calorimeterData.getFactory().getFactoryNumber();
            //计算校验码
            int ll = NettyUtil.get10HexNum(cenhigh)+NettyUtil.get10HexNum(cenlow)+NettyUtil.get10HexNum(add3)+NettyUtil.get10HexNum(add4)+NettyUtil.get10HexNum(add5)+NettyUtil.get10HexNum(add6)+NettyUtil.get10HexNum(cont)+NettyUtil.get10HexNum(factory);
            String check = NettyUtil.get16HexNum(ll);
            if(check.length()<2){
                check = "0" + check;
            }else{
                check = check.substring(check.length()-2);
            }
            String response = "AA "+ cenlow +" "+ cenhigh + " " + add3 + " " + add4 + " " + add5 + " " + add6 + " " + cont + " " + factory + " 00 00 00 00 00 " + check + " FF ";
            String revertStr = response.replace(" ", "");
            NettyUtil.writeToClient(revertStr,channel,"读取热表数据");
            CountDownLatch countDownLatch = new CountDownLatch(1);
            new Thread(new RedisRun(countDownLatch,redisUtil,calorimeterData.getCalorimeterId(),cont)).start();
            countDownLatch.await();
            String result = RedisRun.result;
            if(!result.equals("00")){
                failureMsg.append("<br/>热表"+calorimeterData.getCalorimeterId()+"采集失败");
            }
        }
        if(failureMsg.toString().equals("")){
            return AjaxResult.success();
        }else{
            return AjaxResult.error(failureMsg.toString());
        }
    }

    /**
     * 校验热量表代码
     */
    @PostMapping("/checkCalorimeterDataCodeUnique")
    @ResponseBody
    public String checkCalorimeterDataCodeUnique(BaseCalorimeterData baseCalorimeterData)
    {
        return baseCalorimeterDataService.checkCalorimeterDataCodeUnique(baseCalorimeterData);
    }

    /**
     * 加载热量表数列表
     */
    @GetMapping("/treeData")
    @ResponseBody
    public List<Ztree> treeData()
    {
        List<Ztree> ztrees = baseCalorimeterDataService.selectCalorimeterTree();
        return ztrees;
    }
}
